package com.onurokan.someone4me;

import java.util.HashSet;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.validation.Valid;

import org.apache.commons.codec.binary.Base64;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.onurokan.someone4me.role.dao.AuthorityDao;
import com.onurokan.someone4me.role.domain.Authority;
import com.onurokan.someone4me.role.domain.AuthorityTypeEnum;
import com.onurokan.someone4me.user.dao.UserDao;
import com.onurokan.someone4me.user.domain.User;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

	private static final String PRIVATE_MESSAGE_KEY = "#someone4me#";
	private static final String DUPLICATE_EMAIL_KEY = "Duplicate\\sentry.*for\\skey\\s\\'email\\'";
	private static final String DUPLICATE_USERNAME_KEY = "Duplicate\\sentry.*for\\skey\\s\\'username\\'";
	private static final Logger logger = LoggerFactory
			.getLogger(HomeController.class);

	@Autowired
	UserDao userDao;

	@Autowired
	AuthorityDao authorityDao;
	
	@Autowired
	MailServer mailServer;

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! the client locale is " + locale.toString());

		return "home";
	}

	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String login(ModelMap modelMap) {
		modelMap.put("user", new User());
		fillLoginPage(modelMap);
		return "login";
	}

	@RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
	public String loginerror(ModelMap modelMap) {
		modelMap.put("user", new User());
		fillLoginPage(modelMap);
		modelMap.addAttribute("error", "true");
		return "login";

	}

	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String register(@Valid User user, BindingResult result,
			ModelMap modelMap) {
		if (result.hasErrors()) {
			fillLoginPage(modelMap);
			return "login";
		}

		user.setAccountNonExpired(true);
		user.setAccountNonLocked(true);
		user.setCredentialsNonExpired(true);
		user.setEnabled(true);

		Set<Authority> authoritySet = new HashSet<Authority>();
		Authority userAuthority = authorityDao
				.loadAuthorityByEnumType(AuthorityTypeEnum.ROLE_USER);
		if (userAuthority == null) {
			userAuthority = new Authority();
			userAuthority.setId(0);
			userAuthority.setRole(AuthorityTypeEnum.ROLE_USER.name());
			authorityDao.addAuthority(userAuthority);
		}
		authoritySet.add(userAuthority);
		user.setAuthoritySet(authoritySet);

		try {
			userDao.addUser(user);
		} catch (ConstraintViolationException e) {
			ResourceBundle resources = ResourceBundle.getBundle("messages");
			String detailedMessage = e.getSQLException().getMessage();
			Pattern pattern = Pattern.compile(DUPLICATE_USERNAME_KEY);
			Matcher matcher = pattern.matcher(detailedMessage);
			if (matcher.find()) {
				result.addError(new FieldError("user", "username", resources
						.getString("Unique.user.username")));
				fillLoginPage(modelMap);
				return "login";
			}
			pattern = Pattern.compile(DUPLICATE_EMAIL_KEY);
			matcher = pattern.matcher(detailedMessage);
			if (matcher.find()) {
				result.addError(new FieldError("user", "email", resources
						.getString("Unique.user.email")));
				fillLoginPage(modelMap);
				return "login";
			}
		}

		String activationCode = new String(Base64.encodeBase64((user.getId()
				+ PRIVATE_MESSAGE_KEY + user.getUsername()).getBytes()));
		String activationUrl = "http://localhost:8080/someone4me/activate?code="
				+ activationCode;
		// mailServer.sendMail("activation@someone4me.com",
		// "onurtekdas@gmail.com", "someone4me", activationUrl);
		mailServer.sendMail("activation@someone4me.com", user.getEmail(),
				"someone4me", activationUrl);

		return "activation";
	}

	@RequestMapping(value = "/activate", method = RequestMethod.GET)
	public String activate(String code, ModelMap modelMap) {
		String decodedText = new String(Base64.decodeBase64(code.getBytes()));
		Pattern pattern = Pattern.compile("([0-9]+)" + PRIVATE_MESSAGE_KEY
				+ "(.*)");
		Matcher matcher = pattern.matcher(decodedText);
		if (matcher.find()) {
			String username = matcher.group(2);
			Long id = Long.parseLong(matcher.group(1));
			if (username != null && id >= 0) {
				User user = userDao.loadUserByUsername(username);
				if (user != null && user.getId() == id && !user.getEnabled()) {
					user.setEnabled(true);
					user.resetTemporaryFields();
					userDao.saveUser(user);
					return "home";
				}
			}
		}
		return "invalidlink";
	}

	private void fillLoginPage(ModelMap modelMap) {
		modelMap.put("dayList", User.getDayList());
		modelMap.put("monthList", User.getMonthList());
		modelMap.put("yearList", User.getYearList());
		ResourceBundle resources = ResourceBundle.getBundle("messages");
		modelMap.put("weakPasswordMsg",
				resources.getString("Weak.user.password"));
		modelMap.put("mediumPasswordMsg",
				resources.getString("Medium.user.password"));
		modelMap.put("strongPasswordMsg",
				resources.getString("Strong.user.password"));
		modelMap.put("PasswordDoesnMatchMsg",
				resources.getString("DoesntMatch.user.password"));
	}
}
